package nsl.com.util.excel.basic;


import nsl.com.util.excel.bean.ExcelPoint;
import nsl.com.util.excel.bean.SheetHead;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;


import java.util.ArrayList;
import java.util.List;

/**
 * Attention:rowIndex,columnIndex both begin with 0.
 *
 * Description: find cells according conditions.
 * Created by 4790K_NSL on 2017/4/29.
 */
public class UtilExcelLocate {

    /**
     *  用于判断有效行.
     *  比如如果 有效Row 前30个Cell至少由一个不为null or ''.则定义为有效行
     */
    static private int VALIDATED_ROW_COUNTER=30;

    /**
     * 在sheet内，查找 cell字符串形式和keyString 一致的cell, 将找到excelPoint放入数组，并返回.
     * @param sheet
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint> locateCellByString(Sheet sheet, String keyString){
        List<ExcelPoint> list=new ArrayList<>();
        if(sheet==null || keyString ==null){
            return list;
        }
        for (Row row : sheet ) {
            list.addAll(locateCellInRowByString(row,keyString));
        }
        return list;
    }

    /**
     * 从指定列中找出字符串形式相同的Cell,将找到的Cell的ExcelPoint,装入数组并返回.
     * @param workbook
     * @param sheetName
     * @param columnIndex 指定列,列名为整数序号形式.起始为0
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint>  locateCellInColumnByString(Workbook workbook,String sheetName,int columnIndex,String keyString){
        return locateCellInColumnByString(workbook.getSheet(sheetName),columnIndex,keyString);
    }


    /**
     * 从指定列中找出字符串形式相同的Cell,将找到的Cell的ExcelPoint,装入数组并返回.
     * @param workbook
     * @param sheetName
     * @param columnAddress  指定列,列名为字母形式.起始为A=0
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint>  locateCellInColumnByString(Workbook workbook,String sheetName,String columnAddress,String keyString){
        int columnIndex= UtilExcelCoordinateConverter.convertColumnAddressFromLetter2Index(columnAddress);
        return locateCellInColumnByString(workbook.getSheet(sheetName),columnIndex,keyString);
    }

    /**
     * 在sheet指定的column列内，查找 cell字符串形式和keyString 一致的cell, 将找到excelPoint放入数组，并返回.
     * @param sheet
     * @param columnIndex
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint>  locateCellInColumnByString(Sheet sheet, int columnIndex,String keyString){
        List<ExcelPoint> list=new ArrayList<>();
        if(sheet==null || keyString ==null || columnIndex<0){
            return list;
        }
        for (Row row : sheet ) {
            Cell cell=row.getCell(columnIndex);
            String cellValue= UtilExcelCell.getCellStringValue(cell);
            if (cellValue != null) {
                if(cellValue.trim().equals(keyString.trim())){
                    ExcelPoint point=new ExcelPoint(cell.getRowIndex(),cell.getColumnIndex());
                    list.add(point);
                }
            }
        }
        return list;
    }

    /**
     * 在指定的Row内，查找 cell字符串形式和keyString 一致的cell, 将招的excelPoint放入数组，并返回.
     * @param workbook
     * @param rowIndex
     * @param sheetName
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint>  locateCellInRowByString(Workbook workbook,int rowIndex,String sheetName,String keyString){
        return locateCellInRowByString(workbook.getSheet(sheetName),rowIndex,keyString);
    }

    /**
     * 在sheet指定的rowIndex行内，查找 cell字符串形式和keyString 一致的cell, 将招的excelPoint放入数组，并返回.
     * @param sheet
     * @param rowIndex
     * @param keyString
     * @return
     */
    static  public List<ExcelPoint>  locateCellInRowByString(Sheet sheet, int rowIndex,String keyString){
        List<ExcelPoint> list=new ArrayList<>();
        if(sheet==null || keyString ==null || rowIndex<0){
            return list;
        }
        Row row=sheet.getRow(rowIndex);
        List rowList=locateCellInRowByString(row,keyString);
        list.addAll(rowList);
        return list;
    }


    /**
     * 在指定的Row内，查找 cell字符串形式和keyString 一致的cell, 将招的excelPoint放入数组，并返回.
     * @param row
     * @param keyString
     * @return
     */
    static  private List<ExcelPoint> locateCellInRowByString(Row row,String keyString){
        List<ExcelPoint> list=new ArrayList<>();
        if(row==null || keyString==null){
            return  list;
        }else{
            for(Cell cell:row){
                String cellValue= UtilExcelCell.getCellStringValue(cell);
                if(!(cellValue==null || cellValue.trim().equals("") || keyString==null || keyString.equals(""))){
                    if(cellValue.trim().equals(keyString.trim())){
                        ExcelPoint point=new ExcelPoint(cell.getRowIndex(),cell.getColumnIndex());
                        list.add(point);
                    }
                }
            }
        }
        return list;
    }

    /**
     * 寻找最大的有效行.
     * 有效行:该行 不是 仅有格式,该行前30列,必须由不为空的内容,则该行为由有效行.
     * 对指定的sheet,从 beginRow开始查找,返回行sheet中的最大有效行的行号.
     * 行号以0为起点开始计算.
     * 如果 没有有效行,比如只有表头或者最大行号比beginRow还要小,则返回-1.表示无有效行.
     * @param sheet
     * @param beginRowIndex 起始行号.一般指表头.
     * @return
     */
    static public int findMaxValidatedRow(Sheet sheet ,int beginRowIndex){
        int resultLastRow=-1;
        int lastRow=sheet.getLastRowNum();

        System.out.println(lastRow);
        if(lastRow<=beginRowIndex){
            return -1;
        }
        boolean validatedRow=false;

        for(int i=lastRow;i>beginRowIndex;i--){
            Row row=sheet.getRow(lastRow);
            for(int j=0;j<VALIDATED_ROW_COUNTER;j++){
                Cell cell=row.getCell(j);
                if(cell!=null){
                    String cellValue=UtilExcelCell.getCellStringValue(cell);
                    if(!cellValue.trim().equals("")){
                        resultLastRow=i;
                        validatedRow=true;
                        break;
                    }
                }
            }
            if(validatedRow){
                break;
            }
        }
        return resultLastRow;
    }

    /**
     * 寻找最大的有效行.
     * 有效行:该行 不是 仅有格式,该行前30列,必须由不为空的内容,则该行为由有效行.
     * 对指定的sheet,从 beginRow开始查找,返回行sheet中的最大有效行的行号.
     * 行号以0为起点开始计算.
     * 如果 没有有效行,比如只有表头或者最大行号比beginRow还要小,则返回-1.表示无有效行.
     * @param sheet
     * @param sheetHead
     * @return
     */
    static public int findMaxValidatedRow(Sheet sheet ,SheetHead sheetHead){
        int bottom=sheetHead.getBottom();
        return findMaxValidatedRow(sheet,bottom+1);
    }
}
